
/**
 * 
 * 文本统计分析
 * 
 * 题目描述

有一个文件，包含以一定规则写作的文本，请统计文件中包含的文本数量。

规则如下：

文本以 ";" 分隔，最后一条可以没有 ";" ，但空文本不能算语句，比如
COMMAND A; ;
只能算一条语句。
注意，无字符/空白字符/制表符都算作"空"文本；
 
文本可以跨行，比如下面，是一条文本，而不是三条
COMMAND A
AND
COMMAND B;
文本支持字符串，字符串为成对的单引号(')或者成对的双引号(")，字符串可能出现用转义字符(\)处理的单双引号("your input is\"")和转义字符本身，比如
COMMAND A "Say \"hello\"";
支持注释，可以出现在字符串之外的任意位置注释以”--“开头，到换行结束，比如
COMMAND A; -- this is comment
COMMAND -- comment
A AND COMMAND B;
注意字符串内的”--“，不是注释。

输入描述
文本文件

输出描述
包含的文本数量

用例
输入	COMMAND TABLE IF EXISTS "UNITED STATE";
COMMAND A GREAT (
    ID ADSAB,
    download_length INTE-GER,  -- test
    file_name TEXT,
    guid TEXT,
    mime_type TEXT,
    notifica-tionid INTEGER,
    original_file_name TEXT,
    pause_reason_type INTEGER,
    resumable_flag INTEGER,
    start_time INTEGER,
    state INTEGER,
    folder TEXT,
    path TEXT,
    total_length INTE-GER,
    url TEXT
);
输出	2
说明	无

 */

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

/**
  * 
  题目解析
梳理一下题目信息：

一行中可以有多条文本，比如一行输入为：abc;abc;abc; 此时该行有三条文本。
一条文本以分号结束
成对双引号、成对单引号中的分号，无法作为一条文本结束的标志
注释符号后面的分号，无法作为一条文本结束的标志
成对双引号、成对单引号中的注释符号失效
成对双引号、成对单引号中可能存在转义字符
本题要我们求解文本条数，其实可以转化为求解有效分号个数。

而无效分号，其实就是：

成对双引号、成对单引号中的分号
注释符号后面的分号
我的解题思路如下，假设一行字符串为line：

首先，将line中的转义双引号、转义单引号去掉，避免影响成对双引号、成对单引号的判断
然后，将line中的成对双引号及其中内容、成对单引号及其中内容去除，这样可以简单粗暴的去除成对双引号、成对单引号中的注释符号、分号
之后，将line中注释内容（即：‘-’及其后内容）去掉，这样可以简单粗暴的去除注释中的分号
此时line中就只会剩下分号，我们需要处理一些特殊情况，比如空文本不能算语句，我们可以将line中的空白字符去除掉
经过上一步处理，如果line中存在空白文本，则去除空白字符后，必然会出现类似于 abc;; 这种连续分号的现象，此时我们应该将连续分号替换为单个分号
经过上一步处理，还有一种特殊情况，比如 ;abc 这种，我们需要去除开头分号
最后，line中剩余几个分号，就代表此行存在几个文本
上面逻辑，如果使用字符串操作来写，则较为复杂，我这里直接使用了正则表达式来处理。

另外，需要注意的是，题目描述中说

文本以”;”分隔，最后一条可以没有”;”
这句话的意思应该是，最后一行输入中的最后一条文本，可以没有分号。

比如最后一行为 abc;abc

此时最后一行其实有两条文本，因为最后一条可以没有分号。

关于最后一行，我们可以粗暴的直接给它拼接一个分号，这样话，无论最后一行的最后一条有没有分号，我们都能保证前面的逻辑可以统计到最后一行。

2023.09.05 根据考友提示，上面逻辑存在漏洞，成对双引号、成对单引号之间的内容不能直接替换为空串，因为对于如下情况：

"abc";"abc";"abc";
其实应该是3行。

我们可以将成对双引号、成对单引号之间的内容替换为简单串，比如a

2024.02.08

之前题目描述中关于注释的描述好像抄错了。

实际考试题目中，是以 "--" 两个-作为注释标志
之前博客是将 "-" 一个-作为注释表示
另外补充一个用例，比如：

\";
其中\"也是一个字符，算是有内容，因此这个用例有1个文本。

之前代码直接将 \" 和 \' 替换为了空，因此之前代码逻辑输入上面用例会返回0个文本

  */

public class 文本统计分析 {
    
    public static void main(String[] args) {

        try{

            Scanner scanner = new Scanner(System.in).useDelimiter("[,\n]");

            List<String> inputStrList = new LinkedList<>();

            while (scanner.hasNextLine()) {

                String lineStr = scanner.nextLine();

                 // 本地测试时，以输入空行作为结束条件，实际考试时无需此逻辑
                 if (lineStr.equals("")) break;

                 inputStrList.add(lineStr);

            }

            StringBuilder builder = new StringBuilder();
            for(String line : inputStrList){
                line = line.replaceAll("\\\\[\"']", "a") // 替换\"和\'为普通字符
                .replaceAll("\".*?\"", "a") //将成对双引号及其中内容替换为普通串
                .replaceAll("'*?'", "a") //将成对单引号及其中内容替换为普通串
                .replaceAll("--.+", "") //将--及其往后的注释替换为空串
                .replaceAll("\\s+", "") //将空白字符替换为空串
                .replaceAll(";+", ";"); //将连续分号替换为单个分号

                builder.append(line);

            }

            // 题目描述说：文本以”;”分隔，最后一条可以没有”;”
            // 为了避免复杂处理，这里无论最后一条文本有没有分号，都加一个
            builder.append(";");

            // 下面处理主要是为了处理跨行文本
            /***
             * 比如
             * aaaa;
             * ;aaaa
             *
             * 比如
             * ;aaaa
             * ;aaaa
             */
            String s = builder.toString().replaceAll(";+", ";").replaceAll("^;", "");

            // 记录文本条数
            int count = 0;
        
            for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ';') count++;
            }

            System.out.println(count);


        }catch(Exception e){

            e.printStackTrace();
        }
    }
}
